﻿
namespace n_PointPanel
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using n_UserModule;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using n_OS;

//*****************************************************
//图形编辑器容器类
public class PointPanel : Panel
{
	public delegate void D_Changed();
	public D_Changed Changed;
	
	public int Per;
	public const int ConstPer = 9;
	public bool[][] PointSet;
	
	int MouseOnXN;
	int MouseOnYN;
	
	int LatticeXN;
	int LatticeYN;
	
	Cursor Cursor1;
	//Cursor Cursor2;
	
	SolidBrush BackBrush;
	
	Pen CrossPen1;
	Pen CrossPen8;
	
	public int TipW;
	public int TipH;
	
	public bool isFont;
	
	public Graphics g;
	public Bitmap back;
	public int BufferImageWidth, BufferImageHeight;
	
	//摄像机位置
	public static float CamMidX;
	public static float CamMidY;
	//摄像机放缩比
	public static float CamScale;
	bool isInited = false;
	
	bool LeftPress;
	float lastX;
	float lastY;
	
	public Brush DotBrush;
	
	byte[] BayerPattern = {
		0,  32,  8, 40,  2, 34, 10, 42,
        48, 16, 56, 24, 50, 18, 58, 26,
        12, 44,  4, 36, 14, 46,  6, 38,
        60, 28, 52, 20, 62, 30, 54, 22,
         3, 35, 11, 43,  1, 33,  9, 41,
        51, 19, 59, 27, 49, 17, 57, 25,
        15, 47,  7, 39, 13, 45,  5, 37,
        63, 31, 55, 23, 61, 29, 53, 21
	};
	byte[] BayerPattern2 = {
		0,  8, 2,  10,
        12, 4, 14, 6,
        3, 11,  1, 9,
        15, 7, 13, 5,
	};
	
	Bitmap temp;
	public bool UseOld = false;
	
	//构造函数
	public PointPanel( int WidthN, int HeightN, bool[][] Set ) : base()
	{
		SetStyle(ControlStyles.UserPaint |
		         ControlStyles.AllPaintingInWmPaint |
		         ControlStyles.OptimizedDoubleBuffer |
		         ControlStyles.ResizeRedraw |
		         ControlStyles.SupportsTransparentBackColor,true);
		
		this.Dock = DockStyle.Fill;
		this.ImeMode = ImeMode.NoControl;
		
		Per = ConstPer;
		isFont = false;
		
		SetSize( WidthN, HeightN, Set );
		
		MouseOnXN = -1;
		MouseOnYN = -1;
		
		lastX = 0;
		lastY = 0;
		
		TipW = 8;
		TipH = 8;
		
		Cursor1 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "FontPointer.cur" );
		//Cursor2 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "myPoint2.cur" );
		
		this.Cursor = Cursor1;
		
		this.MouseMove += new MouseEventHandler( UserMouseMove );
		this.MouseUp += new MouseEventHandler( UserMouseUp );
		this.MouseDown += new MouseEventHandler( UserMouseDown );
		this.MouseWheel += new MouseEventHandler( UserMouseWheel );
		this.MouseLeave += new EventHandler( UserMouseLeave );
		
		BackBrush = new SolidBrush( Color.WhiteSmoke );
		CrossPen1 = new Pen( Color.FromArgb( 230, 230, 230 ) );
		CrossPen8 = new Pen( Color.Black, 3 );
		
		DotBrush = Brushes.CornflowerBlue;
		
		ResetScale();
	}
	
	//复位界面放缩
	public void ResetScale()
	{
		if( isInited ) {
			return;
		}
		isInited = true;
		CamMidX = Width/2;
		CamMidY = Height/2;
		CamScale = 1;
	}
	
	public void SetSize( int WidthN, int HeightN, bool[][] Set )
	{
		BufferImageWidth = WidthN * Per + 1;
		BufferImageHeight = HeightN * Per + 1;
		back = new Bitmap( BufferImageWidth, BufferImageHeight );
		g = Graphics.FromImage( back );
		//g.SmoothingMode = SmoothingMode.HighQuality
		g.SmoothingMode = SmoothingMode.HighSpeed;
		
		LatticeXN = WidthN;
		LatticeYN = HeightN;
		
		
		if( UseOld ) {
			bool[][] t = PointSet;
			PointSet = Set;
			for( int i = 0; i < t.Length && i < PointSet.Length; ++i ) {
				for( int j = 0; j < t[i].Length && j < PointSet[i].Length; ++j ) {
					PointSet[i][j] = t[i][j];
				}
			}
			return;
		}
		
		//判断是否需要重新构造点阵信息, 并自动加载以前的点阵信息
		if( Set == null || Set.Length != WidthN || Set[0].Length != HeightN ) {
			
			PointSet = new bool[ WidthN ][];
			for( int i = 0; i < WidthN; ++i ) {
				PointSet[ i ] = new bool[ HeightN ];
			}
			if( Set != null ) {
				for( int i = 0; i < PointSet.Length && i < Set.Length; ++i ) {
					for( int j = 0; j < PointSet[i].Length && j < Set[i].Length; ++j ) {
						PointSet[i][j] = Set[i][j];
					}
				}
			}
		}
		else {
			PointSet = Set;
		}
	}
	
	//设置图片
	public void SetImage( Bitmap bmp, int Gray, int DDType )
	{
		
		if( temp == null || temp.Width != bmp.Width || temp.Height != bmp.Height ) {
			temp = new Bitmap( LatticeXN, LatticeYN );
		}
		Graphics g = Graphics.FromImage( temp );
		g.DrawImage( bmp, 0, 0, LatticeXN, LatticeYN );
		
		
		//temp = new Bitmap( bmp );
		
		if( DDType == 4 ) {
			SetMap( Gray );
		}
		else {
			SetMapDD( Gray, DDType );
		}
	}
	
	//设置图片
	public void SetMap( int Gray )
	{
		for( int xx = 0; xx < LatticeXN; ++xx ) {
			for( int yy = 0; yy < LatticeYN; ++yy ) {
				
				Color c = temp.GetPixel( xx, yy );
				
				//int gray = c.R + c.G + c.B;
				int gray = (int)(0.299 * c.R + 0.587 * c.G + 0.114 * c.B);
				temp.SetPixel( xx, yy, Color.FromArgb( gray, 0, 0 ) );
			}
		}
		for( int xx = 0; xx < LatticeXN; ++xx ) {
			for( int yy = 0; yy < LatticeYN; ++yy ) {
				
				Color c = temp.GetPixel( xx, yy );
				
				//int gray = c.R + c.G + c.B;
				int gray = c.R;
				int newg = 0;
				if( gray >= Gray ) {
					newg = 255;
					PointSet[xx][yy] = false;
				}
				else {
					newg = 0;
					PointSet[xx][yy] = true;
				}
				int err = gray - newg;
				if( xx + 1 < temp.Width ) {
					Color cc = temp.GetPixel( xx + 1, yy );
					int g = cc.R + err * 7/16;
					if( g < 0 ) g = 0;
					if( g > 255 ) g = 255;
					temp.SetPixel( xx + 1, yy, Color.FromArgb( g, 0, 0 ) );
				}
				if( xx > 0 && yy + 1 < temp.Height ) {
					Color cc = temp.GetPixel( xx - 1, yy + 1 );
					int g = cc.R + err * 3/16;
					if( g < 0 ) g = 0;
					if( g > 255 ) g = 255;
					temp.SetPixel( xx - 1, yy + 1, Color.FromArgb( g, 0, 0 ) );
				}
				if( yy + 1 < temp.Height ) {
					Color cc = temp.GetPixel( xx, yy + 1 );
					int g = cc.R + err * 5/16;
					if( g < 0 ) g = 0;
					if( g > 255 ) g = 255;
					temp.SetPixel( xx, yy + 1, Color.FromArgb( g, 0, 0 ) );
				}
				if( xx + 1 < temp.Width && yy + 1 < temp.Height ) {
					Color cc = temp.GetPixel( xx + 1, yy + 1 );
					int g = cc.R + err * 1/16;
					if( g < 0 ) g = 0;
					if( g > 255 ) g = 255;
					temp.SetPixel( xx + 1, yy + 1, Color.FromArgb( g, 0, 0 ) );
				}
			}
		}
	}
	
	//设置图片
	public void SetMapDD( int Gray, int DDType )
	{
		int E = 0;
		if( DDType == 1 ) {
			DDType = 0;
			E = 30;
		}
		for( int x = 0; x < LatticeXN; ++x ) {
			
			int err = E;
			if( x % 2 == 0 ) {
				err = -E;
			}
			
			for( int y = 0; y < LatticeYN; ++y ) {
				
				Color c = temp.GetPixel( x, y );
				
				//int gray = c.R + c.G + c.B;
				int gray = (int)(0.299 * c.R + 0.587 * c.G + 0.114 * c.B);
				
				Gray += err;
				err = -err;
				
				//4位抖动
				if( DDType == 1 ) {
					if( c.A == 0 || gray * 128 / Gray / 16 >= BayerPattern2[x%4 * 4 + y%4] ) {
						PointSet[x][y] = false;
					}
					else {
						PointSet[x][y] = true;
					}
				}
				//8位抖动
				else if( DDType == 2 ) {
					if( c.A == 0 || gray * 128 / Gray / 4 >= BayerPattern[x%8 * 8 + y%8] ) {
						PointSet[x][y] = false;
					}
					else {
						PointSet[x][y] = true;
					}
				}
				//无抖动
				else {
					if( c.A == 0 || gray * 128 / Gray >= 128 ) {
						PointSet[x][y] = false;
					}
					else {
						PointSet[x][y] = true;
					}
				}
			}
		}
	}
	
	//==========================================
	
	//左移点阵
	public void MoveUp()
	{
		for( int x = 0; x < PointSet.Length; ++x ) {
			for( int y = 0; y < PointSet[x].Length - 1; ++y ) {
				PointSet[x][y] = PointSet[x][y + 1];
			}
			PointSet[x][PointSet[x].Length - 1] = false;
		}
	}
	
	//左移点阵
	public void MoveDown()
	{
		for( int x = 0; x < PointSet.Length; ++x ) {
			for( int y = PointSet[x].Length - 1; y > 0; --y ) {
				PointSet[x][y] = PointSet[x][y - 1];
			}
			PointSet[x][0] = false;
		}
	}
	
	//左移点阵
	public void MoveLeft()
	{
		for( int x = 0; x < PointSet.Length - 1; ++x ) {
			PointSet[ x ] = PointSet[ x + 1 ];
		}
		PointSet[ PointSet.Length - 1 ] = new bool[ PointSet[ PointSet.Length - 1 ].Length ];
	}
	
	//右移点阵
	public void MoveRight()
	{
		for( int x = PointSet.Length - 1; x > 0; --x ) {
			PointSet[ x ] = PointSet[ x - 1 ];
		}
		PointSet[ 0 ] = new bool[ PointSet[ 0 ].Length ];
	}
	
	//清空点阵
	public void Clear()
	{
		for( int x = 0; x < PointSet.Length; ++x ) {
			for( int y = 0; y < PointSet[ x].Length; ++y ) {
				PointSet[ x ][ y ] = false;
			}
		}
	}
	
	//反色点阵
	public void Reverse()
	{
		for( int x = 0; x < PointSet.Length; ++x ) {
			for( int y = 0; y < PointSet[ x].Length; ++y ) {
				PointSet[ x ][ y ] = !PointSet[ x ][ y ];
			}
		}
	}
	
	//设置间距
	public void SetTip( int w, int h )
	{
		if( w == 0 ) w = 1;
		if( h == 0 ) h = 1;
		
		TipW = w;
		TipH = h;
	}
	
	//==========================================
	
	//重绘事件
	protected override void OnPaint(PaintEventArgs e)
	{
		ShowImage();
		
		
		//禁用图像模糊效果
		e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
		e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
		
		e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
		
		GraphicsState gs = e.Graphics.Save();
		
		float RolX = Width/2;
		float RolY = Height/2;
		
		//摄像机按照中心位置进行旋转
		//SG.Rotate( RolX, RolY, CamAngle );
		//摄像机按照中心位置进行放缩
		e.Graphics.TranslateTransform( RolX, RolY );
		e.Graphics.ScaleTransform( CamScale, CamScale );
		e.Graphics.TranslateTransform( -RolX, -RolY );
		
		//摄像机移动到指定点
		e.Graphics.TranslateTransform( -(CamMidX - RolX), -(CamMidY - RolY) );
		
		e.Graphics.DrawImage( back, 0, 0 );
		//e.Graphics.DrawImage( back, 0, 0, (int)(back.Width * FScale / 1024), (int)(back.Height * FScale / 1024) );
		
		e.Graphics.Restore( gs );
		e.Graphics.DrawString( "鼠标左键绘制像素\n鼠标中键（滚轮键）擦除像素\n鼠标右键整体拖动图片", n_GUIset.GUIset.Font11, Brushes.SlateGray, 0, 0 );
	}
	
	public void ShowImage()
	{
		//绘制背景
		g.FillRectangle( BackBrush, 0, 0, BufferImageWidth, BufferImageHeight );
		
		//绘制网格
		if( Per != 1 ) {
			DrawCross();
		}
		
		//绘制点亮的点阵
		DrawPointSet();
		
		g.DrawRectangle( Pens.Gray, 0, 0, BufferImageWidth - 1, BufferImageHeight - 1 );
	}
	
	//绘制点亮的点集
	void DrawPointSet()
	{
		int w = Per - 1;
		if( w == 0 ) {
			w = 1;
		}
		if( CoolOK() ) {
			g.FillRectangle( Brushes.Blue, MouseOnXN * Per, MouseOnYN * Per, Per + 1, Per + 1 );
		}
		for( int x = 0; x < LatticeXN; ++x ) {
			for( int y = 0; y < LatticeYN; ++y ) {
				if( PointSet[ x ][ y ] ) {
					g.FillRectangle( DotBrush, x * Per + 1, y * Per + 1, w, w );
					//g.FillEllipse( Brushes.LightGreen, x * Per + 0, y * Per + 0, Per, Per );
				}
			}
		}
	}
	
	//绘制背景点阵
	void DrawCross()
	{
		int WidthNumber = BufferImageWidth / Per;
		int HeightNumber = BufferImageHeight / Per;
		
		for( int i = 0; i <= WidthNumber; ++i ) {
			int x = i * Per;
			g.DrawLine( CrossPen1, x, 0, x, BufferImageHeight - 1 );
		}
		for( int i = 0; i <= HeightNumber; ++i ) {
			int y = i * Per;
			g.DrawLine( CrossPen1, 0, y, BufferImageWidth - 1, y );
		}
		for( int i = 0; i <= WidthNumber; ++i ) {
			int x = i * Per;
			if( i % TipW == 0 ) {
				if( isFont ) {
					g.DrawLine( CrossPen8, x, 0, x, BufferImageHeight - 1 );
				}
				else {
					g.DrawLine( Pens.Silver, x, 0, x, BufferImageHeight - 1 );
				}
			}
		}
		for( int i = 0; i <= HeightNumber; ++i ) {
			int y = i * Per;
			if( i % TipH == 0 ) {
				if( isFont ) {
					g.DrawLine( Pens.Silver, 0, y, BufferImageWidth - 1, y );
				}
				else {
					g.DrawLine( Pens.Silver, 0, y, BufferImageWidth - 1, y );
				}
			}
		}
		//绘制边框
		g.DrawRectangle( Pens.Black, 0, 0, BufferImageWidth - 1, BufferImageHeight - 1 );
	}
	
	//获取坐标点对应的点阵坐标, 无效返回 false
	bool CoolOK()
	{
		if( MouseOnXN >= 0 && MouseOnXN < LatticeXN && MouseOnYN >= 0 && MouseOnYN < LatticeYN ) {
			return true;
		}
		return false;
	}
	
	//鼠标滚轮事件
	public void UserMouseWheel( object sender, MouseEventArgs e )
	{
		Scale( e.Delta, e.X, e.Y );
		
		Invalidate();
	}
	
	public void Scale( int s, float eX, float eY )
	{
		PointF p = GetWorldPoint( eX, eY );
		if( s > 0 ) {
			CamScale *= 1.5f;
		}
		else {
			if( CamScale > 0.05 ) {
				CamScale /= 1.5f;
			}
		}
		PointF p1 = GetWorldPoint( eX, eY );
		CamMidX += p.X - p1.X;
		CamMidY += p.Y - p1.Y;
	}
	
	public PointF GetWorldPoint( float mouseX, float mouseY )
	{
		mouseX = mouseX - Width/2;
		mouseY = mouseY - Height/2;
		
		mouseX = mouseX/CamScale;
		mouseY = mouseY/CamScale;
		
		//double R = Math.Cos( -CamAngle * Math.PI/180 );
		//double I = Math.Sin( -CamAngle * Math.PI/180 );
		//double x = mouseX*R - mouseY*I;
		//double y = mouseX*I + mouseY*R;
		
		double x = mouseX;
		double y = mouseY;
		
		return new PointF( (float)(CamMidX + x), (float)(CamMidY + y) );
	}
	
	//鼠标按下事件
	void UserMouseDown( object sender, MouseEventArgs e )
	{
		this.Focus();
		
		if( e.Button == MouseButtons.Right ) {
			lastX = e.X;
			lastY = e.Y;
		}
		else {
			LeftPress = true;
			if( CoolOK() ) {
				if( e.Button == MouseButtons.Left ) {
					PointSet[ MouseOnXN ][ MouseOnYN ] = true;
				}
				else if( e.Button == MouseButtons.Middle ) {
					PointSet[ MouseOnXN ][ MouseOnYN ] = false;
				}
				else {
					//...
				}
				if( Changed != null ) {
					Changed();
				}
			}
		}
		
		//触发界面显示刷新
		this.Invalidate();
	}
	
	//鼠标松开事件
	void UserMouseUp( object sender, MouseEventArgs e )
	{
		LeftPress = false;
	}
	
	//鼠标移动事件
	void UserMouseMove( object sender, MouseEventArgs e )
	{
		PointF pf = GetWorldPoint( e.X, e.Y );
		
		MouseOnXN = (int)pf.X / Per;
		MouseOnYN = (int)pf.Y / Per;
		
		if( e.Button == MouseButtons.Right ) {
			float ox = -(e.X - lastX) / CamScale;
			float oy = -(e.Y - lastY) / CamScale;
			
			double dx = ox;
			double dy = oy;
			
			CamMidX += (float)dx;
			CamMidY += (float)dy;
			lastX = e.X;
			lastY = e.Y;
		}
		if( CoolOK() ) {
			
			if( LeftPress ) {
				PointSet[ MouseOnXN ][ MouseOnYN ] = true;
			}
			if( e.Button == MouseButtons.Middle ) {
				PointSet[ MouseOnXN ][ MouseOnYN ] = false;
			}
		}
		
		//触发界面显示刷新
		this.Invalidate();
	}
	
	//鼠标离开时
	void UserMouseLeave( object sender, EventArgs e )
	{
		MouseOnXN = -1;
		MouseOnYN = -1;
		
		Invalidate();
	}
}
}


